<template>
    <!-- <button @click="getParams">获取</button> -->
    <article class="form-config-body">
        <el-affix v-if="currentStep === 2" :offset="120">
            <el-card shadow="never">
                <CompList :customer-comp="customerComp" />
            </el-card>
        </el-affix>
        <el-card shadow="never">
            <ControlCard
                ref="ControlCardRef"
                :key="ControlCardKey"
                v-model:form_desc="form_desc"
                :control-card-columns="formDataList" />
        </el-card>
        <el-affix v-if="currentStep === 2" :offset="120">
            <el-card shadow="never">
                <ControlConfig :current-item="currentItem" />
            </el-card>
        </el-affix>
    </article>
</template>
<script lang="tsx" setup>
import { getMarketinGroupgList } from '@/api/smartMarketing/group';
import { reactive, provide, ref, onBeforeMount, computed, defineExpose, nextTick, inject } from 'vue';
import { ElMessage } from 'element-plus';
import { useRoute } from 'vue-router';
import { attrList } from '@/view/customer/manage/configure/api.ts';
import { sourceList } from '@/view/customer/manage/configure/api.ts';

import CompList from './FormConfigComponents/CompList';
import ControlCard from './FormConfigComponents/ControlCard';
import ControlConfig from './FormConfigComponents/ControlConfig';

import { handleFormConfigData, handleFormConfigDataToView } from './utils/DataProcessing';

const currentStep = inject('currentStep');

const form_desc = ref<string>('');
/* 客户属性列表 */
const customerComp = reactive<Array<any>>([]);
const getCustomerComp = async () => {
    const sourceDataList: any = await sourceList(); // 客户属性来源
    const res: any = await attrList();
    // 客户属性添加是否是客户属性的
    for (const iterator of res.data) {
        iterator.is_customer_attr = 1;
        // 客户来源做单独赋值
        if (iterator.system_code === 'source') {
            iterator.attr_val_name = sourceDataList?.data.map((v: any) => v.name).join(',');
        }
    }
    customerComp.splice(
        0,
        customerComp.length,
        ...res.data.filter(v => {
            return v.is_enable !== 0;
        })
    );
};
onBeforeMount(() => {
    getCustomerComp();
});
/* 客户属性列表 */
/* 表单配置项 */
const ControlCardKey = ref('ControlCardKey');
const currentItem: any = ref({});
const currentIndex = ref<number | undefined>();
const formDataList = reactive<Array<any>>([]);
const formDataMap = computed(() => {
    return new Map(formDataList.map((item: any) => [item.id, item]));
});
const formDataSelectList = computed(() => {
    return formDataList.filter((item: any) => ['select', 'radio', 'muti_select'].includes(item.type));
});
const addFormDataItem = (data: any) => {
    if (formDataList.length >= 100) {
        return ElMessage.warning('最多添加100个');
    }
    const IS_SELECT_CUSATTR = ['select', 'muti_select'].includes(data.type) && data.is_customer_attr;
    const key = data.id ?? `${data.type}_${+new Date()}`;
    const formData = {
        ...data,
        key,
        id: key,
        form_title: data.name,
        form_change_title: data.name,
        form_desc: '',
        form_placeholder: '',
        form_value: '',
        customer_attr_id: data.id,
        is_require: true,
        is_desc_write: false,
        is_title_write: false,
        is_tags: false,
        is_rules: false,
        picture_url: [],
        options_list: IS_SELECT_CUSATTR
            ? data.attr_val_name?.split(',').map((v: string) => ({
                  value: v,
                  is_option_write: false,
                  tags_list: []
              }))
            : [],
        rules_list: []
    };
    formDataList.push(formData);
};
const setCurrentItem = (FormDataItem: any, index: number) => {
    currentItem.value = null; // 垃圾回收机制nice🌟
    currentItem.value = FormDataItem;
    currentIndex.value = index;
};
const removeFormDataItem = (i: number) => {
    formDataList.splice(i, 1);
    // 删除后的激活项
    if (i - 1 >= 0) {
        currentItem.value = null; // 垃圾回收机制nice🌟
        currentItem.value = formDataList[i - 1];
        ControlCardRef.value.currentId.value = formDataList[i - 1].key;
    } else {
        if (formDataList[i]) {
            currentItem.value = null; // 垃圾回收机制nice🌟
            currentItem.value = formDataList[i];
            ControlCardRef.value.currentId.value = formDataList[i].key;
        } else {
            currentItem.value = {};
        }
    }
};
const onMoveFormDataItem = (evt: any) => {
    // const itemEl = evt.item // dragged HTMLElement
    // evt.to // target list
    // evt.from // previous list
    // evt.oldIndex // element's old index within old parent
    // evt.newIndex // element's new index within new parent
    // evt.clone // the clone element
    // evt.pullMode // when item is in another sortable: `"clone"` if cloning, `true` if moving
    const { oldIndex, newIndex } = evt;
    const moveItem = formDataList[oldIndex];
    // 切换顺序
    if (oldIndex < newIndex) {
        formDataList.splice(newIndex + 1, 0, formDataList[oldIndex]);
        formDataList.splice(oldIndex, 1);
    } else {
        formDataList.splice(newIndex, 0, formDataList[oldIndex]);
        formDataList.splice(oldIndex + 1, 1);
    }

    // 转化为key字符串
    const toKeysString = (arr: Array<any>, key: string) => {
        return arr
            .map((item: any) => item[key])
            .sort((a: any, b: any) => a - b)
            .join(',');
    };
    const resetFormData = (newIndex: number, oldIndex: number) => {
        const file = ControlCardRef.value.fileList[0];
        formDataList.splice(newIndex, 1);
        formDataList.splice(oldIndex, 0, moveItem);
        ControlCardRef.value.$forceUpdate();
        ControlCardKey.value = `${+new Date()}`;
        nextTick(() => {
            if (file) ControlCardRef.value.fileList[0] = file;
        });
    };
    // 如果移动的是存在关联规则
    if (moveItem.rules_list?.length) {
        // 比较是否可以移动（当前之前的选择索引是否包含当前项的关联key）
        const ruleKeys = toKeysString(moveItem.rules_list, 'related_key');
        if (!ruleKeys) {
            resetFormData(newIndex, oldIndex);
            return ElMessage.error('请先设置关联题目');
        }
        // formDataList.slice(0, newIndex)
        const filterKeys = toKeysString(
            formDataSelectList.value.slice(0, newIndex).filter((item: any) => item.key !== moveItem.key),
            'key'
        );

        const isMoveIt = filterKeys.includes(ruleKeys);
        if (!isMoveIt) {
            resetFormData(newIndex, oldIndex);
            return ElMessage.error('该题已设置关联题目，无法移动到已关联的题目之前');
        }
    }

    // 如果移动的是选择类型控件
    if (['select', 'radio', 'muti_select'].includes(moveItem.type)) {
        const formKeys = formDataList.slice(0, newIndex + 1);
        let RuleKeysString = '';
        for (const item of formKeys) {
            for (const ruleItem of item.rules_list) {
                RuleKeysString += `${ruleItem.related_key},`;
            }
        }

        const isNotMoveIt = RuleKeysString.includes(moveItem.key);
        if (isNotMoveIt) {
            resetFormData(newIndex, oldIndex);
            return ElMessage.error('该题已设置关联题目，无法移动到已关联的题目之前');
        }
    }

    ControlCardRef.value.$forceUpdate();
};

provide('formDataMap', formDataMap);
provide('formDataSelectList', formDataSelectList);
provide('currentItem', currentItem);
provide('currentIndex', currentIndex);
provide('addFormDataItem', addFormDataItem);
provide('setCurrentItem', setCurrentItem);
provide('removeFormDataItem', removeFormDataItem);
provide('onMoveFormDataItem', onMoveFormDataItem);

/* 表单配置项 */

/* 表单校验 */
const setValidCurrentItem = (iterator: any, validindex: number) => {
    setCurrentItem(iterator, validindex);
    ControlCardRef.value.currentId.value = iterator.key;
    let CONTROL_CARD_DOM: any = document.querySelectorAll('#config-card-list .config-card-item');
    let CONTROL_CARD_DOM_ITEM: any = CONTROL_CARD_DOM.item(validindex);
    let App: any = document.querySelector('main.main');
    if (CONTROL_CARD_DOM_ITEM) {
        App?.scrollTo(0, CONTROL_CARD_DOM_ITEM.offsetTop - 50);
    } else {
        // eslint-disable-next-line
        console.error(new Error('#没有找到校验的控件#'));
    }

    /* 释放内存 */
    App = null;
    CONTROL_CARD_DOM = null;
    CONTROL_CARD_DOM_ITEM = null;
};
const ControlCardRef = ref();
const validFormConfig = () => {
    return new Promise((resolve, reject) => {
        const result = ControlCardRef.value?.fileList?.[0]?.url;
        // if (!result) {
        //     ElMessage.error('请上传表单封面~');
        //     return reject(`${result}, 请上传表单封面`);
        // }

        if (!formDataList.length) {
            ElMessage.error('请添加收集表控件~');
            return reject(`${false}, 请添加收集表控件`);
        }

        let validindex = 0;
        for (const iterator of formDataList) {
            const MESSAGE_INDEX = `${validindex + 1}`.padStart(2, '0');
            const optionMap = new Map();
            const message = `请添加${MESSAGE_INDEX}【${iterator.form_title}】选项`;
            switch (iterator.type) {
                case 'carousel':
                    if (!iterator.picture_url.length) {
                        // 校验不能为空
                        ElMessage.error(`请上传${MESSAGE_INDEX}【${iterator.form_title}】图片`);
                        return reject('请上传图片');
                    }
                    break;

                case 'radio':
                case 'muti_select':
                case 'select':
                    // 校验字段本身
                    if (!iterator.options_list.length) {
                        // 校验不能为空
                        ElMessage.error(message);
                        setValidCurrentItem(iterator, validindex);
                        return reject(message);
                    }
                    for (const optionItem of iterator.options_list) {
                        if (!optionItem.value) {
                            // 校验不能为空
                            ElMessage.error(message);
                            setValidCurrentItem(iterator, validindex);
                            return reject(message);
                        } else if (optionMap.has(optionItem.value)) {
                            // 校验不能重复
                            ElMessage.error(`${MESSAGE_INDEX}【${iterator.form_title}】选项内容不允许重复`);
                            setValidCurrentItem(iterator, validindex);
                            return reject(`${MESSAGE_INDEX}【${iterator.form_title}】选项内容不允许重复`);
                        }
                        optionMap.set(optionItem.value, optionItem);
                    }
                    break;
            }

            // 校验规则
            if (iterator.is_rules) {
                if (!iterator.rules_list?.length) {
                    setValidCurrentItem(iterator, validindex);
                    ElMessage.error(`请添加${iterator.form_title}规则~`);
                    return reject(`请添加${iterator.form_title}规则~`);
                }
                iterator.rules_list.forEach((ruleItem: any, i: number) => {
                    const message = `请选择${MESSAGE_INDEX}【${iterator.form_title}】的【关联规则${i + 1}】的关联项`;
                    if (!ruleItem.related_key || !ruleItem.related_value?.length) {
                        setValidCurrentItem(iterator, validindex);
                        ElMessage.error(message);
                        throw new Error(message);
                        // return reject(message);
                    }
                });
            }
            validindex++;
        }
        resolve(true);
    });
};
/* 表单校验 */

const getParams = async (isValid: boolean) => {
    const result = await validFormConfig();
    if (isValid) return result;
    const form = handleFormConfigData(formDataList);
    return {
        desc: form_desc.value,
        cover_image: ControlCardRef.value.fileList?.[0]?.url,
        form
    };
};
const setDetailInfo = (detailInfo: any) => {
    const { config } = detailInfo;
    const formConfigData = handleFormConfigDataToView(config);
    formDataList.splice(0, formDataList.length, ...formConfigData);
    ControlCardRef.value.fileList.length = 0;
    ControlCardRef.value.fileList.push(...(detailInfo.cover_image ? [{ url: detailInfo.cover_image }] : []));
    form_desc.value = detailInfo.desc;
};
defineExpose({
    getParams,
    setDetailInfo
});
</script>

<style lang="scss" scoped>
.el-card {
    overflow: visible;
}

.form-config-body {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
}
</style>
